/*
 * Copyright 2016 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package io.netty.util.concurrent;

import io.netty.util.internal.UnstableApi;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Default implementation which uses simple round-robin to choose next {@link EventExecutor}.
 */
@UnstableApi
public final class DefaultEventExecutorChooserFactory implements EventExecutorChooserFactory {

    public static final DefaultEventExecutorChooserFactory INSTANCE = new DefaultEventExecutorChooserFactory();

    // 单例模式，通过INSTANCE提供一个单例对象
    private DefaultEventExecutorChooserFactory() { }

    /*
    创建一个选择器，从一组EventExecutor中挑选出一个。
    Netty默认的选择策略就是:简单轮询。
     */
    @Override
    public EventExecutorChooser newChooser(EventExecutor[] executors) {
        // 两种Chooser实现都有一个AtomicLong计数器，每次next()先自增再取余

        // 如果数量是2的幂次方数，则采用位运算
        if (isPowerOfTwo(executors.length)) {
            return new PowerOfTwoEventExecutorChooser(executors);
        } else {
            // 否则，对长度进行取余
            return new GenericEventExecutorChooser(executors);
        }
    }

    // 是否是2的幂次方数
    private static boolean isPowerOfTwo(int val) {
        return (val & -val) == val;
        /*
        二进制中，最高位是符号位，0正数、1负数。剩下的就是这个数的绝对值部分。
        原码:设置符号位，其他0填充
        反码:正数的反码与原码相同，负数的反码:除符号位外，其他位取反
        补码:正数的补码与原码相同，负数的补码:除符号位外，其他位取反，然后在最后一位加1(计算机使用补码)

        如下举例:
            5:00000000 00000000 00000000 00000101(原码)
            5:00000000 00000000 00000000 00000101(反码)
            5:00000000 00000000 00000000 00000101(补码)

           -5:10000000 00000000 00000000 00000101(原码)
           -5:11111111 11111111 11111111 11111010(反码)
           -5:11111111 11111111 11111111 11111011(补码)

           5 & -5 = 00000000 00000000 00000000 00000001 = 1 不是2的幂次方数
           8 & -8 = 00000000 00000000 00000000 00001000
                  & 11111111 11111111 11111111 11111000
                  = 00000000 00000000 00000000 00001000 = 8 是2的幂次方数
         */
    }

    public static void main(String[] args) {
        System.out.println(isPowerOfTwo(6));
        System.out.println(5 & -5);
        /*
        00000000000000000000000000000110
        11111111111111111111111111111010
         */


        System.out.println(Integer.toBinaryString(5));
        System.out.println(Integer.toBinaryString(-5));
    }

    // 2的幂次方数的选择器，位运算
    private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
        private final AtomicInteger idx = new AtomicInteger();
        private final EventExecutor[] executors;

        PowerOfTwoEventExecutorChooser(EventExecutor[] executors) {
            this.executors = executors;
        }

        @Override
        public EventExecutor next() {
            // 计数器自增 & 长度-1，和HashMap一样
            return executors[idx.getAndIncrement() & executors.length - 1];
        }
    }

    // 普通的选择器，取余
    private static final class GenericEventExecutorChooser implements EventExecutorChooser {
        private final AtomicLong idx = new AtomicLong();
        private final EventExecutor[] executors;

        GenericEventExecutorChooser(EventExecutor[] executors) {
            this.executors = executors;
        }

        @Override
        public EventExecutor next() {
            return executors[(int) Math.abs(idx.getAndIncrement() % executors.length)];
        }
    }
}
